package cn.iocoder.yudao.module.reading.controller.admin.file;

import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO;
import cn.iocoder.yudao.module.reading.service.audio.AudioService;
import cn.iocoder.yudao.module.reading.service.file.ReadingFileService;
import cn.iocoder.yudao.module.reading.framework.util.StaticResourceUrlUtils;
import cn.iocoder.yudao.module.reading.controller.admin.file.vo.AudioUploadRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

/**
 * 管理后台 - 音频文件管理
 * 
 * @author 李晨
 */
@Tag(name = "管理后台 - 音频文件管理")
@RestController
@RequestMapping("/reading/audio-file")
@Validated
@Slf4j
public class AdminAudioFileController {

    @Resource
    private ReadingFileService readingFileService;
    @Resource
    private AudioService audioService;
    @Resource
    private StaticResourceUrlUtils staticResourceUrlUtils;

    /**
     * 检查当前用户是否为管理员
     * 音频资源文件上传只允许管理员操作
     */
    private void checkAdminPermission() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException(401, "用户未登录");
        }
        if (!UserTypeEnum.ADMIN.getValue().equals(loginUser.getUserType())) {
            throw new ServiceException(403, "权限不足，只有管理员可以上传音频资源文件");
        }
    }

    // =============================================
    // 音频资源文件上传
    // =============================================

    @PostMapping("/resource")
    @Operation(summary = "上传音频资源文件")
    @PreAuthenticated
    public CommonResult<AudioUploadRespVO> uploadAudioResource(
            @Parameter(description = "音频分类") @RequestParam("category") String category,
            @Parameter(description = "语言类型") @RequestParam(value = "language", required = false) String language,
            @Parameter(description = "音频文件") @RequestParam("audio") MultipartFile audioFile) {

        // 检查管理员权限 - 音频资源只允许管理员上传
        checkAdminPermission();

        log.info("上传音频资源，分类: {}, 语言: {}, 文件名: {}", category, language, audioFile.getOriginalFilename());

        try {
            // 上传文件，服务层返回包含时长等信息的结果（包含相对路径）
            AudioUploadRespVO uploadResult = readingFileService.uploadAudioResource(category, language, audioFile);

            // 转换音频URL为完整URL返回给前端
            String fullUrl = staticResourceUrlUtils.toFullUrl(uploadResult.getAudioUrl());
            uploadResult.setAudioUrl(fullUrl);

            log.info("音频资源上传成功，相对路径转换为完整URL: {}, 时长: {} 秒", fullUrl, uploadResult.getDuration());

            return success(uploadResult);
        } catch (Exception e) {
            log.error("上传音频资源失败", e);
            return error(500, "上传音频失败: " + e.getMessage());
        }
    }

    @PostMapping("/audio/{audioId}/cover")
    @Operation(summary = "上传音频封面")
    @PreAuthenticated
    public CommonResult<String> uploadAudioCover(
            @Parameter(description = "音频ID") @PathVariable("audioId") Long audioId,
            @Parameter(description = "封面文件") @RequestParam("cover") MultipartFile coverFile) {

        // 检查管理员权限 - 音频封面只允许管理员上传
        checkAdminPermission();

        log.info("上传音频封面，音频ID: {}, 文件名: {}", audioId, coverFile.getOriginalFilename());
        
        try {
            // 上传文件，服务层返回相对路径
            String relativePath = readingFileService.uploadAudioCover(audioId, coverFile);
            // 转换为完整URL返回给前端
            String fullUrl = staticResourceUrlUtils.toFullUrl(relativePath);
            log.info("音频封面上传成功，相对路径: {}, 完整URL: {}", relativePath, fullUrl);

            return success(fullUrl);
        } catch (Exception e) {
            log.error("上传音频封面失败", e);
            return error(500, "上传封面失败: " + e.getMessage());
        }
    }

    // =============================================
    // 预签名URL获取
    // =============================================

    @GetMapping("/resource/presigned-url")
    @Operation(summary = "获取音频资源上传预签名URL")
    @PreAuthenticated
    public CommonResult<FilePresignedUrlRespVO> getAudioResourcePresignedUrl(
            @Parameter(description = "音频分类") @RequestParam("category") String category,
            @Parameter(description = "语言类型") @RequestParam(value = "language", required = false) String language,
            @Parameter(description = "文件名") @RequestParam("fileName") String fileName) {
        
        // 检查管理员权限
        checkAdminPermission();
        
        try {
            FilePresignedUrlRespVO presignedUrl = readingFileService.getAudioResourcePresignedUrl(category, language, fileName);
            return success(presignedUrl);
        } catch (Exception e) {
            log.error("获取音频资源预签名URL失败", e);
            return error(500, "获取预签名URL失败: " + e.getMessage());
        }
    }

    // =============================================
    // 文件验证接口
    // =============================================

    @PostMapping("/validate/audio")
    @Operation(summary = "验证音频文件")
    @PreAuthenticated
    public CommonResult<String> validateAudioFile(
            @Parameter(description = "音频文件") @RequestParam("audio") MultipartFile audioFile,
            @Parameter(description = "最大文件大小（MB）") @RequestParam(value = "maxSizeMB", defaultValue = "50") Integer maxSizeMB) {
        
        // 检查管理员权限
        checkAdminPermission();
        
        try {
            long maxSize = maxSizeMB * 1024L * 1024L; // 转换为字节
            readingFileService.validateAudioFile(audioFile, maxSize);
            return success("音频文件验证通过");
        } catch (Exception e) {
            log.error("音频文件验证失败", e);
            return error(400, "文件验证失败: " + e.getMessage());
        }
    }

    @PostMapping("/validate/image")
    @Operation(summary = "验证图片文件")
    @PreAuthenticated
    public CommonResult<String> validateImageFile(
            @Parameter(description = "图片文件") @RequestParam("image") MultipartFile imageFile,
            @Parameter(description = "最大文件大小（MB）") @RequestParam(value = "maxSizeMB", defaultValue = "10") Integer maxSizeMB) {
        
        // 检查管理员权限
        checkAdminPermission();
        
        try {
            long maxSize = maxSizeMB * 1024L * 1024L; // 转换为字节
            readingFileService.validateImageFile(imageFile, maxSize);
            return success("图片文件验证通过");
        } catch (Exception e) {
            log.error("图片文件验证失败", e);
            return error(400, "文件验证失败: " + e.getMessage());
        }
    }

    @GetMapping("/next-id")
    @Operation(summary = "获取下一个音频资源ID")
    @PreAuthenticated
    public CommonResult<Long> getNextAudioResourceId() {
        // 检查管理员权限
        checkAdminPermission();

        Long nextId = audioService.getNextAudioResourceId();
        return success(nextId);
    }
}
